package com.res.share.filter;


import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.google.common.util.concurrent.RateLimiter;
import com.res.share.common.utils.IpAddressUtils;
import org.springframework.stereotype.Component;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;

/**
 * IP限制过滤器
 */
@WebFilter(filterName = "ipLimitFilter",urlPatterns = {"/**"})
@Component
public class IpLimitFilter implements Filter {

    // 根据IP分不同的令牌桶, 每天自动清理缓存
    private static LoadingCache<String, RateLimiter> caches = CacheBuilder.newBuilder()
            .maximumSize(1000)
            .expireAfterWrite(5, TimeUnit.HOURS)
            .build(new CacheLoader<String, RateLimiter>() {
                @Override
                public RateLimiter load(String key) throws Exception {
                    // 新的IP初始化 (个限流每秒两令牌响应)
                    //每个IP每秒只能调用两次该API
                    return RateLimiter.create(5);
                }
            });

    /**
     * @Description 核心处理代码
     * @param servletRequest
     * @param servletResponse
     * @param chain
     * @throws IOException
     * @throws ServletException
     * @see javax.servlet.Filter#doFilter(javax.servlet.ServletRequest,
     *      javax.servlet.ServletResponse, javax.servlet.FilterChain)
     */
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain)
            throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        HttpServletResponse response = (HttpServletResponse) servletResponse;
        String requestURI = request.getRequestURI();
        if ((requestURI + "").contains("/doc.html")
                || (requestURI + "").contains("/swagger-resources")
                || (requestURI + "").contains("/v2")
                || (requestURI + "").contains("/api-docs")
                || (requestURI + "").contains("/webjars")
                || (requestURI + "").contains("/limitIp")
                || (requestURI + "").contains("/static")
                || (requestURI + "").contains("/favicon.ico")
                || (requestURI + "").contains("/file")) {
            chain.doFilter(request, response);
            return;
        }
        // 获取用户IP
        String ip = IpAddressUtils.getIpAddress(request);
        try {
            RateLimiter limiter = caches.get(ip);
            if (!limiter.tryAcquire()) {
                request.getRequestDispatcher("/limitIp/overLimitIP.html").forward(request, response);
                return;
            }
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
        chain.doFilter(request, response);
    }

    @Override
    public void destroy() {

    }
}
